Skip to content

feat(dpop,webmention,activitypub,mastodon-api): close near-term Anglesite feature gaps - #423

Merged
davidwkeith merged 4 commits into
mainfrom
claude/anglesite-feature-gaps-8qmd6r
Jul 24, 2026
Merged

feat(dpop,webmention,activitypub,mastodon-api): close near-term Anglesite feature gaps#423
davidwkeith merged 4 commits into
mainfrom
claude/anglesite-feature-gaps-8qmd6r

Conversation

@davidwkeith

Copy link
Copy Markdown
Owner

Summary

Implements the tractable slice of a repo-wide sweep for optional/deferred spec requirements Anglesite is likely to request next — four independent increments:

  • @dwk/dpopEdDSA (Ed25519) + ES512 proof algorithms. The spec had marked both "not implemented yet — widen on demand"; this widens the allow-list with ES512 (P-521 + SHA-512) and EdDSA over RFC 8037 OKP keys, including the OKP RFC 7638 thumbprint. Ed448 stays rejected as crv_mismatch (no Web Crypto support in the Workers runtime); symmetric algorithms and none remain excluded.
  • Catalog — specificationURL back-filled onto every route claim. Anglesite-app's consumer (WorkerRouteClaims.validate, Anglesite-app#829) requires the field on every prefix claim; spec/catalog.md had tracked the back-fill as a follow-up. All 27 remaining claims now carry it (the one deliberate exception: webdav's /dav-credentials, a package-defined exact-claim admin endpoint with no governing external spec), and scripts/catalog-gate.mjs now enforces the prefix-claim requirement mechanically.
  • @dwk/webmention — deleted-source re-send (§3.1.5, the spec's last known gap). SendOptions gains an opt-in sentLog recording every accepted notification (createD1SentLog, own webmentions_sent table, strongly consistent per the non-functional rules), and resendForDeletedSource(source) re-sends to every recorded target once the source serves 410 Gone, so receivers re-verify and drop the mention. Accepted (or endpoint-less) re-sends clear their log row; failed ones keep it for a later retry. Two new observability events.
  • @dwk/activitypub + @dwk/mastodon-apifollow notifications (the deferred phase-2 gap). #onFollow now stores a new follower's Follow (or FEP-1b12 Group membership Join) in the actor's inbox — a re-Follow from a still-recorded follower is not a fresh notification — the __client/notifications classifier surfaces those rows, and notificationEntity maps them to Mastodon's type: "follow", so clients like Tusky and Pixelfed see new-follower notifications (with actor-profile hydration for name/avatar via the existing queued fetch).

Specs updated accordingly (spec/packages/dpop.md, spec/catalog.md, spec/packages/webmention.md, spec/packages/mastodon-api.md).

Packages affected

@dwk/dpop, @dwk/webmention, @dwk/activitypub, @dwk/mastodon-api (plus repo-root catalog.json, scripts/catalog-gate.mjs, and specs)

Checklist

  • Read the relevant spec(s) under spec/packages/ and updated them if
    behaviour changed
  • Added/updated colocated tests (src/*.test.ts)
  • Ran the local CI gate: pnpm lint && pnpm format:check && pnpm typecheck && pnpm build && pnpm test
  • Added a changeset (pnpm changeset) if this touches a publishable
    package
  • Updated catalog.json / conformance/status.json if this adds a new
    mountable worker or changes conformance status — catalog.json route claims back-filled; no new worker, conformance status unchanged

🤖 Generated with Claude Code

https://claude.ai/code/session_01XT45PcE3pgXgsQffQDWdhW


Generated by Claude Code

claude added 4 commits July 24, 2026 03:54
Widen the allow-list the spec marked "not implemented yet — widen on
demand": ES512 (P-521 + SHA-512) and EdDSA over RFC 8037 OKP keys,
including the OKP RFC 7638 thumbprint. Ed448 stays rejected as
crv_mismatch — the Workers runtime has no Web Crypto support for it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT45PcE3pgXgsQffQDWdhW
Anglesite-app's consumer requires the field on every prefix claim (only
a specification can approve child paths) and recommends it on exact
claims; spec/catalog.md had tracked the back-fill as a follow-up. Every
claim now carries it except webdav's /dav-credentials, a package-defined
exact-claim admin endpoint with no governing external spec. The catalog
gate now enforces the prefix-claim requirement mechanically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT45PcE3pgXgsQffQDWdhW
The spec's last known gap, a SHOULD: SendOptions gains an opt-in sentLog
recording every accepted notification (createD1SentLog — own
webmentions_sent table, strongly consistent), and
resendForDeletedSource(source) re-sends to every recorded target once
the source serves 410 Gone so receivers re-verify and drop the mention.
Accepted (or endpoint-less) re-sends clear their log row; failed ones
keep it for a later retry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT45PcE3pgXgsQffQDWdhW
Close the deferred phase-2 gap: #onFollow stores a new follower's
Follow (or FEP-1b12 Group membership Join) in the actor's inbox — a
re-Follow from a still-recorded follower is not a fresh notification —
the __client/notifications classifier surfaces those rows, and
notificationEntity maps them to Mastodon's type "follow" so clients
like Tusky and Pixelfed see new-follower notifications. The inbox path
also queues the follower's actor-profile fetch for name/avatar
hydration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT45PcE3pgXgsQffQDWdhW

Copy link
Copy Markdown
Owner Author

The github-advanced-security check failure is a GitHub-side service error, not something in this diff: the Copilot code-scanning agent aborted before analyzing anything with CAPIError: 400 model_not_supported (its configured sweagent-capi:claude-opus-4.6 model was rejected by Copilot's own API). Nothing pushable fixes it — a re-run once GitHub's side recovers should clear it.

The repo's own gates are passing on this head: release-gate ✅, integration ✅, Analyze (actions) ✅, with build-test and the JS/TS CodeQL analysis still running. I'll keep watching and follow up if any of those go red.


Generated by Claude Code

@davidwkeith
davidwkeith merged commit dc59912 into main Jul 24, 2026
8 of 9 checks passed
@davidwkeith
davidwkeith deleted the claude/anglesite-feature-gaps-8qmd6r branch July 24, 2026 03:58

@davidwkeith davidwkeith left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all four increments (@dwk/dpop EdDSA/ES512, catalog specificationURL backfill, @dwk/webmention deleted-source resend, @dwk/activitypub+@dwk/mastodon-api follow notifications) against the repo's architecture rules and CONTRIBUTING.md.

Code: No correctness or security issues found.

  • @dwk/dpop: ES512 correctly pairs P-521/SHA-512; EdDSA correctly restricts to kty: "OKP"/crv: "Ed25519" (Ed448 rejected as crv_mismatch, matching the documented Workers Web Crypto limitation). jwk.kty is checked against the algorithm spec before any curve/signature check, so there's no algorithm-confusion opening. The OKP thumbprint canonicalization ({crv, kty, x}) matches RFC 8037 §3.2's required member order.
  • @dwk/webmention: sent-log.ts's D1 table name is validated against /^[A-Za-z_][A-Za-z0-9_]*$/ before being interpolated into DDL; all row values go through bound ?1/?2/?3 params — no injection surface. resendForDeletedSource delegates to the existing sendWebmention (already routed through @dwk/safe-fetch) rather than adding a new fetch path.
  • @dwk/activitypub: #onFollow's new-follower check (SELECT before INSERT OR IGNORE, then conditionally #storeInbox) has no await between the read and the write, so there's no TOCTOU race given the Durable Object's single-threaded request processing.
  • Verified independently: every "match": "prefix" route in the resulting catalog.json now carries a specificationURL (the one deliberate exact-claim exception, /dav-credentials, is correctly excluded per the gate rule added in catalog-gate.mjs).

Verification: Built a worktree off this branch and ran pnpm lint, pnpm format:check, pnpm build — all clean. pnpm test for the four touched packages passed (622/623 individually-verified; the one failure only reproduced under full-suite parallel load in my sandbox and passed cleanly in isolation — consistent with GitHub's own build-test check already being green on this PR).

CONTRIBUTING.md conformance: PR title/body match the Conventional Commits + template format, checklist is complete, changesets are present for all three publishable-package changes, and specs (dpop.md, catalog.md, webmention.md, mastodon-api.md) were updated in the same PR and accurately reflect the code.

Not a code issue, FYI: like #422, the github-advanced-security check failure here is GitHub's own Copilot agent hitting CAPIError: 400 model_not_supported, not a finding against this diff.

No changes requested.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants